home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgramD2.iso
/
Borland
/
Borland C++ V5.02
/
GDIDEMO.PAK
/
LINE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-06
|
6KB
|
192 lines
//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
//
// MoveToLineTo demo window
//----------------------------------------------------------------------------
#include <owl/pch.h>
#include <owl/dc.h>
#include "line.h"
#include <math.h>
//
//
//
DEFINE_RESPONSE_TABLE1(TMoveToLineToWindow, TBaseDemoWindow)
EV_WM_SIZE,
END_RESPONSE_TABLE;
IMPLEMENT_CASTABLE1(TMoveToLineToWindow, TBaseDemoWindow);
//
//
//
TMoveToLineToWindow::TMoveToLineToWindow() : TBaseDemoWindow()
{
Rotation = 0;
PointCount = MaxPoints;
Iconized = false;
RotatePoints();
}
//
//
//
void
TMoveToLineToWindow::EvSize(uint sizeType, TSize& size)
{
TBaseDemoWindow::EvSize(sizeType, size);
Invalidate();
if (sizeType == SIZE_MINIMIZED) {
if (!Iconized) {
Rotation = 0;
Iconized = true;
PointCount = IconicPoints;
RotatePoints();
}
}
else {
if (Iconized) {
Rotation = 0;
Iconized = false;
PointCount = MaxPoints;
RotatePoints();
}
}
}
//
//
//
void
TMoveToLineToWindow::TimerTick()
{
RotatePoints();
if (Iconized) {
// Iconized windows don't process paint messages, so we'll manually
// update the image here. Doing this painting during the timer tick
// will slow things down a bit, especially with several of these
// windows iconized at the same time.
//
Paint(TClientDC(*Parent), false, TRect());
}
else {
// In terms of Windows resources and system wide performance, letting
// paint do the work is 'faster' because it reduces the CPU time spent
// handling each timer tick. Paint messages are low priority, so other
// messages like mouse clicks and other user input get processed first.
// The downside is that the paint messages are handled last, when
// there's nothing else to do, which can make animation look a bit jerky
// on a busy machine.
//
Invalidate(false); // Let the Paint method draw the new figure...
}
}
//
//
//
void
TMoveToLineToWindow::RotatePoints()
{
// NOTE: all figures are in radians
const float M_2PI = 2 * M_PI; // 2 pi radians in a circle
float StepAngle = M_2PI / PointCount; // angular distance between points
Rotation += M_PI / 32; // Increment the angle of rotation of figure
if (Rotation > StepAngle)
Rotation -= StepAngle; // Keep rotation less than distance between points
// The loop below has i walking through the Points array, while j walks
// simultaneously through the angles to each point on the circle.
// Incrementing j by StepAngle moves j to the next point on the circle with
// no complicated arithmetic (everything has been set up in advance of the
// loop). Initializing j with Rotation causes the entire figure to shift
// clockwise a small amount.
//
int i;
float j;
for (i = 0, j = Rotation; i < PointCount; i++, j += StepAngle) {
Points[i].X = cos(j); // These values will be multiplied by the
Points[i].Y = sin(j); // current radius at display time.
}
}
//
//
//
void
TMoveToLineToWindow::Paint(TDC& dc, bool, TRect&)
{
TRect rect;
if (Iconized)
Parent->GetClientRect(rect);
else
GetClientRect(rect);
int centerX = rect.right / 2;
int centerY = rect.bottom / 2;
int radius = min(centerY, centerX);
// The follow memory DC operations are not required to draw lines, but
// were added to reduce screen flicker and speed up screen updates.
//
TMemoryDC memDC(dc);
TBitmap bitmap(dc, radius*2, radius*2);
memDC.SelectObject(bitmap);
// Initiallize the new bitmap to all white.
//
memDC.PatBlt(0, 0, radius*2, radius*2, WHITENESS);
// The Ellipse and the loop are all that's really needed to draw. If you
// substitute dc for memDC, the draws will go directly to the screen.
// (Though the figure would no longer be centered, since the figure is drawn
// on a memDC bitmap, and the bitmap is then centered on the dc...)
// Since this line window is animated, it is frequently updated, which would
// cause the window to spend most of its time flickering if the dc were
// used. Thus, the need for memory DC operations. If the window were not
// animated, drawing onto the dc would look just fine.
//
memDC.Ellipse(0, 0, radius*2, radius*2);
int i,j;
for (i = 0; i < PointCount; i++) {
for (j = i + 1; j < PointCount; j++) {
memDC.MoveTo(radius + floor(Points[i].X * radius),
radius + floor(Points[i].Y * radius));
memDC.LineTo(radius + floor(Points[j].X * radius),
radius + floor(Points[j].Y * radius));
}
}
// Now transfer what was drawn on the (invisible) memory DC onto the visible
// dc. This one BitBlt transfer is much faster than the many
// individual operations that were performed above.
//
dc.BitBlt(centerX-radius, centerY-radius, radius*2, radius*2,
memDC, 0, 0, SRCCOPY);
// Restore original bitmap before leaving
//
memDC.RestoreBitmap();
// Footnotes: Drawing this figure doesn't require a memory DC. Animating
// the figure requires a memory DC only to reduce flicker to a tolerable
// level.
// To make the animation faster still, (but use more memory, too),
// you could keep that memory DC hanging around between screen paints -
// constructing a DC takes some effort, and we're constructing one every
// time we get a timer message. You'd get the biggest improvement in
// animation speed by calculating a sequence of bitmaps, then just
// displaying them in the proper sequence. This demo reconstructs the
// points list and redraws the figure for every timer message - a lot of
// work for the CPU, but it's code is simpler and doesn't use as much
// memory as more elaborate schemes might.
// A challenge: Turn the rotating figure into a ball that bounces off the
// walls of the window. Don't forget the english (spin) the ball should
// pick up when bouncing off the wall...
}